package com.ala4.oxcafe.boot.async;

import cn.idev.excel.ExcelWriter;
import cn.idev.excel.FastExcelFactory;
import cn.idev.excel.write.metadata.WriteSheet;
import com.ala4.oxcafe.boot.ExcelExport;
import com.ala4.oxcafe.boot.repository.ExportTaskDTO;
import com.ala4.oxcafe.boot.utils.ExcelUtil;
import com.ala4.oxcafe.common.utils.object.ObjectUtil;
import com.ala4.oxcafe.enums.AsyncTaskStateEnum;
import com.ala4.oxcafe.export.ExportPage;
import com.ala4.oxcafe.export.ExportResult;
import lombok.extern.slf4j.Slf4j;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

/**
 * 异步导出任务
 *
 * @author PING
 * @version 1.0.0
 * @date 2025/8/1 16:49
 */
@Slf4j
public class AsyncExportTaskRunnable implements Runnable {

    /**
     * 第一次返回的结果
     */
    private ExportResult<?> exportResult;
    private final Object target;
    private final Method method;
    private final Object[] args;
    private final ExportPage exportPage;
    private final ExcelExport excelExport;
    private final ExportTaskDTO exportTaskDTO;
    // 导出模版
    private final ExportAsyncTemplate exportAsyncTemplate;

    private final ExportFutureManager exportFutureManager;

    public AsyncExportTaskRunnable(Object target, Method method, Object[] args,
                                   ExportResult<?> exportResult, ExportPage exportPage, ExcelExport excelExport,
                                   ExportTaskDTO exportTaskDTO,
                                   ExportAsyncTemplate exportAsyncTemplate, ExportFutureManager exportFutureManager) {
        this.exportResult = exportResult;
        this.target = target;
        this.method = method;
        this.args = args;
        this.exportPage = exportPage;
        this.excelExport = excelExport;
        this.exportTaskDTO = exportTaskDTO;
        this.exportAsyncTemplate = exportAsyncTemplate;
        this.exportFutureManager = exportFutureManager;
    }

    @Override
    public void run() {

        Path tempFile = null;
        try {
            // 更新开始执行任务
            exportAsyncTemplate.updateTaskStatus(exportTaskDTO, AsyncTaskStateEnum.DOING);

            // 第一次查询的数据
            List<?> dataList = exportResult.getRecords();
            // 总页数
            Integer pageTotal = exportResult.getTotalPage();

            // 创建临时文件
            tempFile = Files.createTempFile(excelExport.excelName(), ".xlsx");
            FileOutputStream fileOutputStream = new FileOutputStream(tempFile.toFile());

            ExcelWriter excelWriter = ExcelUtil.buildOutputExcel(fileOutputStream, excelExport);

            try (fileOutputStream;excelWriter) {
                WriteSheet writeSheet = FastExcelFactory.writerSheet(excelExport.excelName()).build();
                // 写入第一次的数据
                excelWriter.write(dataList, writeSheet);

                int currentPage = exportPage.getPageNum() + 1;
                while (currentPage <= pageTotal) {

                    // 设置页数
                    exportPage.setPageNum(currentPage);
                    // 设置不count
                    exportPage.setSearchCount(false);
                    long _startTime = System.currentTimeMillis();
                    log.info("开始处理第[{}]页数据", currentPage);
                    exportResult = ExcelUtil.requestDataPage(target, method, args);

                    dataList = exportResult.getRecords();
                    excelWriter.write(dataList, writeSheet);
                    log.info("结束处理第[{}]页数据,总数量[{}],毫秒[{}]", currentPage, dataList.size(),(System.currentTimeMillis()-_startTime));
                    currentPage = currentPage + 1;

                    dataList.clear();
                }
            }

            exportAsyncTemplate.doWhenFinish(exportTaskDTO,tempFile);

        } catch (Exception exception) {
            // 导出出现异常
            log.error("export task execute error", exception);
            exportAsyncTemplate.doWhenOccurException(exportTaskDTO, exception);
        } finally {

            // 异步管理器中移除任务
            exportFutureManager.remove(exportTaskDTO.getTaskCode());

            // 确保临时文件清理
            if (ObjectUtil.isNotNull(tempFile) && Files.exists(tempFile)) {
                try {
                    Files.delete(tempFile);
                } catch (IOException ex) {
                    log.error("临时文件删除失败: {}", tempFile, ex);
                }
            }
        }
    }

}
